import csv
import numpy as np
import requests
import pandas as pd
import json
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.graph_objects as go
import plotly.express as px
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus'] = False
f_path = "C://Windows//Fonts/malgun.ttf"
font_name = font_manager.FontProperties(fname=f_path).get_name()
rc('font', family=font_name)
#버스 행정동별 승차인원
busPP = pd.read_csv('./data/bus_congestion.csv', encoding='cp949')
busPP = busPP.drop(busPP.columns[0:2], axis=1)
busPP.head()
| 행정동 | 승차인원 | |
|---|---|---|
| 0 | 동선동 | 88065 |
| 1 | 와룡동 | 6787 |
| 2 | 종로1·2·3·4가동 | 39868 |
| 3 | 삼선동 | 60435 |
| 4 | 교남동 | 28437 |
#버스 행정동별 운행대수
busWK = pd.read_csv('./data/bus_work.csv')
busWK.head()
| 행정동 | 운행대수 | |
|---|---|---|
| 0 | 천호2동 | 1203 |
| 1 | 성내2동 | 962 |
| 2 | 암사1동 | 634 |
| 3 | 천호1동 | 1015 |
| 4 | 강일동 | 2364 |
#혼잡도 = 일일 승하차승객수 / 운행대수 -> 버스마다 크기와 좌석수가 다르기 때문에 어느정도의 오차가 발생할 수 있음
busResult = pd.merge(busPP, busWK, on='행정동', how='inner')
busResult['혼잡도'] = busResult['승차인원']/busResult['운행대수']
busResult = busResult.sort_values(by='혼잡도')
busResult
| 행정동 | 승차인원 | 운행대수 | 혼잡도 | |
|---|---|---|---|---|
| 20 | 구기동 | 158 | 1946 | 0.081192 |
| 13 | 홍지동 | 716 | 1539 | 0.465237 |
| 80 | 사근동 | 2485 | 2633 | 0.943790 |
| 12 | 연희동 | 4319 | 4281 | 1.008876 |
| 22 | 평창동 | 940 | 502 | 1.872510 |
| ... | ... | ... | ... | ... |
| 275 | 독산2동 | 36387 | 537 | 67.759777 |
| 362 | 송파1동 | 35906 | 426 | 84.286385 |
| 304 | 노량진2동 | 27889 | 320 | 87.153125 |
| 37 | 다산동 | 9055 | 98 | 92.397959 |
| 109 | 전농2동 | 26489 | 136 | 194.772059 |
399 rows × 4 columns
busResult.to_excel('./busConfusion.xlsx')
fig = go.Figure()
fig.add_trace(go.Scatter(x=busResult['행정동'], y=busResult['혼잡도'], mode='lines', name='Congestion of bus'))
average_get_on = [busResult['혼잡도'].mean()] * len(busResult)
fig.add_trace(go.Scatter(x=busResult['행정동'], y=average_get_on, mode='lines', name='AVERAGE'))
fig.update_layout(
title='Bus Congestion',
xaxis_title='행정동',
yaxis_title='Congestion',
xaxis_rangeslider_visible=True # rangeslider 추가
)
# plotly 그래프 출력
fig.show()
busResult_mean = busResult['승차인원'].mean()
busResult_mean
26290.44611528822
fig = go.Figure()
fig.add_trace(go.Scatter(x=busResult['행정동'], y=busResult['승차인원'], mode='lines', name='GET ON'))
average_get_on = [busResult['승차인원'].mean()] * len(busResult)
fig.add_trace(go.Scatter(x=busResult['행정동'], y=average_get_on, mode='lines', name='AVERAGE'))
fig.update_layout(
title='탑승인원',
xaxis_title='행정동',
yaxis_title='탑승인원',
xaxis_rangeslider_visible=True # rangeslider 추가
)
# plotly 그래프 출력
fig.show()
fig = go.Figure()
average_working_bus = [busResult['운행대수'].mean()] * len(busResult)
fig.add_trace(go.Scatter(x=busResult['행정동'], y=average_working_bus, mode='lines', name='AVERAGE'))
fig.add_trace(go.Scatter(x=busResult['행정동'], y=busResult['운행대수'], mode='lines', name='WORKING BUS'))
fig.update_layout(
title='운행대수',
xaxis_title='행정동',
yaxis_title='운행대수',
xaxis_rangeslider_visible=True # rangeslider 추가
)
# plotly 그래프 출력
fig.show()
localDong = pd.read_csv('./data/LOCAL_PEOPLE_DONG.csv')
localDong.head()
| 기준일ID | 시간대구분 | 행정동코드 | 총생활인구수 | |
|---|---|---|---|---|
| 0 | 20230701 | 0 | 11140680 | 7387.6458 |
| 1 | 20230701 | 0 | 11230730 | 21126.2155 |
| 2 | 20230701 | 0 | 11380632 | 14489.8440 |
| 3 | 20230701 | 0 | 11380650 | 10987.3091 |
| 4 | 20230701 | 0 | 11380625 | 43851.1827 |
hangCode = pd.read_excel('./data/행정동코드.xlsx')
hangCode.head()
| 행정동코드 | 시도명 | 시군구명 | 행정동 | |
|---|---|---|---|---|
| 0 | 11110530 | 서울 | 종로구 | 사직동 |
| 1 | 11110540 | 서울 | 종로구 | 삼청동 |
| 2 | 11110550 | 서울 | 종로구 | 부암동 |
| 3 | 11110560 | 서울 | 종로구 | 평창동 |
| 4 | 11110570 | 서울 | 종로구 | 무악동 |
#행정동별 생활인구수
localPP = pd.merge(localDong, hangCode, on='행정동코드', how='inner')
localPP = localPP.drop(columns=['시간대구분'])
localPP = localPP.groupby('행정동', as_index=False)['총생활인구수'].mean()
localPP
| 행정동 | 총생활인구수 | |
|---|---|---|
| 0 | 가락1동 | 31985.669088 |
| 1 | 가락2동 | 26452.145546 |
| 2 | 가락본동 | 34019.237987 |
| 3 | 가리봉동 | 9798.276317 |
| 4 | 가산동 | 38799.521196 |
| ... | ... | ... |
| 418 | 효창동 | 8450.758638 |
| 419 | 후암동 | 12282.800313 |
| 420 | 휘경1동 | 16851.335217 |
| 421 | 휘경2동 | 18609.358113 |
| 422 | 흑석동 | 30518.453337 |
423 rows × 2 columns
#행정동별 사업체개수 및 종사자수
localWP = pd.read_excel('./data/사업체현황종사자수.xlsx')
#행정동별 숙박 및 음식점 개수, 종사자수
localAF = pd.read_excel('./data/숙박및음식점.xlsx')
busResult_R = busResult.merge(localPP, on='행정동', how='inner') \
.merge(localWP, on='행정동', how='inner') \
.merge(localAF, on='행정동', how='inner')
busResult_R
| 행정동 | 승차인원 | 운행대수 | 혼잡도 | 총생활인구수 | 사업체수 | 총종사자수 | 사업체수_음식및숙박 | 종사자수_음식및숙박 | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 사근동 | 2485 | 2633 | 0.943790 | 21279.456646 | 1310 | 10537 | 444 | 1305 |
| 1 | 연희동 | 4319 | 4281 | 1.008876 | 36262.183429 | 3420 | 13243 | 518 | 1426 |
| 2 | 평창동 | 940 | 502 | 1.872510 | 18597.975900 | 1321 | 4321 | 142 | 481 |
| 3 | 마장동 | 3632 | 1802 | 2.015538 | 20304.767346 | 4030 | 12518 | 226 | 561 |
| 4 | 둔촌1동 | 1134 | 539 | 2.103896 | 4332.939179 | 36 | 286 | 2 | 8 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 381 | 독산2동 | 36387 | 537 | 67.759777 | 13981.066521 | 1531 | 4184 | 212 | 381 |
| 382 | 송파1동 | 35906 | 426 | 84.286385 | 29260.778138 | 3406 | 16572 | 511 | 1700 |
| 383 | 노량진2동 | 27889 | 320 | 87.153125 | 16756.667812 | 2011 | 6809 | 258 | 565 |
| 384 | 다산동 | 9055 | 98 | 92.397959 | 14017.096233 | 2023 | 8723 | 215 | 633 |
| 385 | 전농2동 | 26489 | 136 | 194.772059 | 15133.874650 | 1358 | 5460 | 149 | 404 |
386 rows × 9 columns
import warnings
warnings.filterwarnings("ignore")
correlation_matrix = busResult_R.corr().round(2)
sns.heatmap(data=correlation_matrix, annot=True, cmap='bwr')
<Axes: >